﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Wormhole.Engine.CardLibrary.CardProperties;

namespace Wormhole.Engine.CardLibrary.BaseCardTypes
{
	/// <author>Rodney McKay</author>
	/// <date>04 April 2008</date>
	/// <summary>
	/// This is a base class for all cards in the game.
	/// </summary>
	public abstract class Card
	{
		#region Delegates
		/// <summary>
		/// The delegate for the event that is raised when the card is played.
		/// </summary>
		public delegate void CardPlayedDelegate(Card card);

		/// <summary>
		/// the delegate for the event that is raised when the card input status changes.
		/// </summary>
		/// <param name="status">The new input status.</param>
		public delegate void InputStatusChangedDelegate(InputStatus status);

		/// <summary>
		/// The delegate for the event that is fired when a the card is selected.
		/// </summary>
		public delegate void CardSelectedDelegate(Card card);
		#endregion

		#region Events
		/// <summary>
		/// The event that is raised when the card is played.
		/// </summary>
		public event CardPlayedDelegate CardPlayed;

		/// <summary>
		/// This event is raised when the input status changes.
		/// </summary>
		public event InputStatusChangedDelegate InputStatusChanged;

		/// <summary>
		/// This event is raised when the card is selected.
		/// </summary>
		public event CardSelectedDelegate CardSelected;
		#endregion

		#region Properties

		#region ID
		/// <summary>
		/// The Unique identiefier for the instance of the card.
		/// </summary>
		public int ID { get; set; }
		#endregion

		/// <summary>
		/// The card title.
		/// </summary>
		public abstract string Title { get; }

		/// <summary>
		/// The card subtitle.
		/// This property will be null for cards that do not have a subtitle like
		/// gear, event and obstacle cards.
		/// </summary>
		public abstract string Subtitle { get; }

		/// <summary>
		/// The card traits.
		/// </summary>
		public abstract Traits Traits { get; }

		/// <summary>
		/// The card game text.
		/// </summary>
		public abstract string GameText { get; }

		/// <summary>
		/// The card lore.
		/// </summary>
		public abstract string Lore { get; }

		/// <summary>
		/// The card collector information.
		/// </summary>
		public abstract CollectorInfo CollectorInfo { get; }

		/// <summary>
		/// The URI to the card image.
		/// </summary>
		public abstract Uri ImageUri { get; }

		#region Owner
		/// <summary>
		/// The card owner.
		/// </summary>
		public Player.Player Owner { get; set; }
		#endregion

		#region Game
		/// <summary>
		/// The game engine.
		/// </summary>
		public Game Game
		{
			get
			{
				if (this.Owner != null)
					return this.Owner.Game;

				return null;
			}
		}
		#endregion

		#region Is Villain Card
		/// <summary>
		/// This value is true if the card is a villain card.
		/// </summary>
		public bool IsVillainCard
		{
			get
			{
				return (this.Traits.Contains(Trait.Obstacle) || this.Traits.Contains(Trait.Adversary));
			}
		}
		#endregion

		#region Input Status
		private InputStatus _inputStatus;
		/// <summary>
		/// This status is used to help indicate what actions are allowed on the card.
		/// </summary>
		public InputStatus InputStatus
		{
			get
			{
				return this._inputStatus;
			}

			set
			{
				if (this._inputStatus != value)
				{
					this._inputStatus = value;
					this.OnInputStatusChanged(value);
				}
			}
		}
		#endregion

		#endregion

		#region Constructor
		/// <summary>
		/// Initialize a new instance of the class.
		/// </summary>
		/// <param name="owner">The card owner</param>
		public Card(Player.Player owner)
		{
			this.Owner = owner;
		}
		#endregion

		#region Play
		/// <summary>
		/// Play the card.
		/// </summary>
		public virtual void Play()
		{
			this.OnCardPlayed(this);
		}
		#endregion

		#region On Play Card
		/// <summary>
		/// Raise the event that a card pas played.
		/// </summary>
		/// <param name="card">The card that was played.</param>
		protected void OnCardPlayed(Card card)
		{
			if (this.CardPlayed != null)
				this.CardPlayed(card);
		}
		#endregion

		#region On Input Status Changed
		/// <summary>
		/// Raise the input status changed event.
		/// </summary>
		/// <param name="status">The new input status.</param>
		protected virtual void OnInputStatusChanged(InputStatus status)
		{
			if (this.InputStatusChanged != null)
				this.InputStatusChanged(status);
		}
		#endregion

		#region On Card Selected
		/// <summary>
		/// Raise the card selected event.
		/// </summary>
		protected void OnCardSelected()
		{
			if (this.CardSelected != null)
				this.CardSelected(this);
		}
		#endregion

		#region Can Play
		/// <summary>
		/// Can the card be played from the players hand?
		/// </summary>
		/// <returns>Returns true if the card can be played.</returns>
		public virtual bool CanPlay()
		{
			return true;
		}
		#endregion

		#region Select Card
		/// <summary>
		/// Select the card.
		/// </summary>
		/// <returns>Returns true if the card could be selected.</returns>
		public bool SelectCard()
		{
			if (this.InputStatus == InputStatus.AllowSelect)
			{
				this.OnCardSelected();
				return true;
			}

			return false;
		}
		#endregion
	}
}
